use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
macro_rules! calculate {
    (eval $e:expr) => {
       let val:usize =  $e;
        println!("{} = {}", stringify!{$e}, val);
    };
}
pub mod a{

}

fn main() {
    // simple_ownership();
    // mutable()
    // thread()
    // box_point()
    // rc_point()
    // mutex_point()
    calculate!{
        eval 1 + 2
    }
}

fn box_point() {
    //将该对象在堆上进行开辟,起到全局共享的作用,不过box比较鸡肋,他只能一个所有权,就是只能有一个指向
    let x = Box::new(Point { x: 1, y: 1 });
    // println!("{}", *x.x);
    //会自动解引用,相当于上面的写法
    println!("{}", x.x);
}
//rc只能在单线程中使用,并且是只读的
fn rc_point() {
    let x = Rc::new(Point { x: 1, y: 1 });

    let x1 = Rc::clone(&x); //借用x克隆完成以后,又把x给还了回去
    let x2 = Rc::clone(&x); //借用x克隆完成以后,又把x给还了回去

    println!("{} {} {}", x1.x, x.x, x2.x);
}
//支持多线程同步的指针，但是只能只读
fn arc_point() {
    let x = Arc::new(Point { x: 1, y: 1 });
    let x1 = Arc::clone(&x);
    let handle = thread::spawn(move || {
        println!("{}", x1.y);
    });
    //借用x克隆完成以后,又把x给还了回去
    let x2 = Arc::clone(&x); //借用x克隆完成以后,又把x给还了回去
    let handle = thread::spawn(move || {
        println!("{}", x2.y);
    });
}
//共享不可变，可变不共享
fn mutex_point() {
    let arc = Arc::new(Mutex::new(Point { x: 1, y: 1 }));
    for i in 0..10 {
        let reference = Arc::clone(&arc);
        let handle = thread::spawn(move || {
            //会在reference的生命周期自动持有锁，并在结束后自动释放锁
            let mut  reference = reference.lock().unwrap();
            reference.x += i;
        });
        println!("111");
        handle.join().expect("TODO: panic message");
    }
    println!("{}", arc.lock().unwrap().x);
}

struct Point {
    // int32类型
    x: i32,
    y: i32,
}
fn simple_ownership() {
    let p1 = Point { x: 25, y: 25 };
    let p2 = p1;
    println!("{} {}", p2.x, p2.y);
}
fn mutable() {
    // 声明变量的时候默认不可变,如果想要可变需要使用mut关键字
    let mut p1 = Point { x: 25, y: 25 };
    p1.x = 1;
    println!("{} {}", p1.x, p1.y);
}

fn simple_borrow() {
    let p1 = Point { x: 25, y: 25 };
    f(&p1);
    println!("{}", p1.x);
    let mut p2 = Point { x: 1, y: 2 };
    f_mut(&mut p2);
    println!("{}", p2.x);
}
//借用,借用完成以后会自动归还指针
fn f(point: &Point) {}

//可变借用,借用完成以后会自动归还指针
fn f_mut(point: &mut Point) {
    point.x = 2
}

fn thread() {
    // let t = thread::spawn(|| {
    //     for i in 1..10 {
    //         println!("{}", i);
    //         thread::sleep(Duration::from_millis(100));
    //     }
    // });
    // t.join().expect("TODO: panic message");

    let p1 = Point { x: 25, y: 25 };
    let t = thread::spawn(move || {
        //此处是一个闭包
        //默认启动一个线程是把p1借用过来,用完回还回去,但是可能这个时候外面函数的生命周期已经结束了,所以不一定还的回去,所以这里会报错
        println!("{}", p1.x);
    });
    t.join().unwrap();

    let p2 = Point { x: 25, y: 25 };
    let t = thread::spawn(
        //将外部指针转移过来使用
        move || {
            //此处是一个闭包
            println!("{}", p2.x);
        },
    );
    t.join().unwrap();
}
